package com.douma._2022_7_2;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.TreeSet;

/**
 * 抖码算法，让算法学习变的简单有趣
 *
 * @作者 : 老汤
 */
public class 跳格子游戏 {

    // 这道题目可以抽象为一个有向图的算法问题。n 个顶点，顶点与顶点之间有依赖关系，也就是边是有向的
    // 需要用到有向图的拓扑排序算法
    // 对于拓扑排序，请学习课程 A【高级篇二：图的经典算法】中的有向图和拓扑排序的章节
    // 链接：https://appvpmptkl94774.pc.xiaoe-tech.com/detail/p_6233e000e4b02b8258568d6c/6
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // 顶点的个数
        int n = Integer.valueOf(sc.nextLine());
        // 使用邻接表来表达图结构
        TreeSet<Integer>[] graph = new TreeSet[n];
        for (int i = 0; i < n; i++) {
            graph[i] = new TreeSet<>();
        }
        // 记录每个顶点的入度
        int[] indegrees = new int[n];
        String line;
        while (!(line = sc.nextLine()).equals("")) {
            String[] data = line.split(" ");
            int a = Integer.valueOf(data[0]);
            if (a < 0 || a >= n) {
                System.out.println("no");
                return;
            }
            int b = Integer.valueOf(data[1]);
            if (b < 0 || b >= n) {
                System.out.println("no");
                return;
            }
            // 有向图：a --> b （跳完格子 a，才会开启 b）
            graph[a].add(b);
            // b 这个顶点的入度 + 1
            indegrees[b]++;
        }

        // 拓扑排序
        Queue<Integer> queue = new LinkedList<>();
        for (int v = 0; v < n; v++) {
            if (indegrees[v] == 0) {
                queue.add(v);
            }
        }
        int index = 0;
        while (!queue.isEmpty()) {
            int v = queue.remove();
            index++;
            for (int w : graph[v]) {
                indegrees[w]--;
                if (indegrees[w] == 0) {
                    queue.add(w);
                }
            }
        }
        if (index != n) {
            System.out.println("no");
        } else {
            System.out.println("yes");
        }

        sc.close();
    }
}
